package com.yanggeng.demo.beginnerguidedemo.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.yanggeng.demo.beginnerguidedemo.utils.DeviceParams;

import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;

/**
 * 保险 理财 年化利率和万份收益折线图
 * Created by yanggeng on 2017/9/6.
 */

public class PayoffLineChart extends View {

    private String[] xAxisStr; //横坐标
    private List<String> yAxisStr = new ArrayList<>(); //纵坐标
    private List<Float> axisValue = new ArrayList<>(); //坐标点纵坐标值

    private List<String> yAxisYearStr = new ArrayList(); //年化纵坐标 文字（默认为 0%—5%）

    private DecimalFormat df = new DecimalFormat("0.00元");
    private DecimalFormat df2 = new DecimalFormat("0.0000");

    private int lineColor = Color.parseColor("#2BABE8");
    private int shadowColor = Color.parseColor("#192BABE8");
    private int titleTextColor = Color.parseColor("#999999");
    private int titleTextSize = DeviceParams.sp2px(getContext(), 12f);
    private int lineWidth = DeviceParams.dip2px(getContext(), 1.5f);
    private int normalLineWidth = DeviceParams.dip2px(getContext(), 0.5f);
    private int normalLineColor = Color.parseColor("#E2E2E2");
    private int axisTextSize = DeviceParams.sp2px(getContext(), 12f);
    private int axisTextColor = Color.parseColor("#999999");
    private int selectedLineColor = Color.parseColor("#80EBC700");
    private int selectedLineWidth = DeviceParams.dip2px(getContext(), 1f);

    private float height; //整体高度
    private float width; //整体宽度
    private float lineChartHeight, lineChartWidth; //折线图高度（除去顶部文字的高度），宽度
    private float yAxisMaxValue; // Y轴最大值
    private float cellHeight, cellWidth; // Y轴平均每份高度，X轴平均每份宽度

    private Paint axisTextPaint; //坐标轴文字
    private Paint bgLinePaint; // 背景线
    private Paint titleTextPaint; //顶部文字
    private Paint linePaint; //折线
    private Paint shadowPaint; //阴影
    private Paint selectedLinePaint; //选中线

    private Path shadowPath;

    public static final int MODE_WEEK = 0x101; // 近七日
    public static final int MODE_MONTH = 0x102; //一个月
    public static final int MODE_3_MONTH = 0x103; //三个月

    public static final int MODE_TYPE_YEAR_FLOAT = 0x104; //年化
    public static final int MODE_TYPE_EARN = 0x105; //万份收益

    private int MODE_DATE = MODE_WEEK; //当前模式，默认近七日
    private int MODE_TYPE = MODE_TYPE_YEAR_FLOAT; //当前模式，默认年化

    private int leftYOffset = 150;
    private int rightOffset = DeviceParams.dip2px(getContext(), 10);
    private LinkedHashMap<Float, Float> coordinate = new LinkedHashMap<>();

    private List<Coordinate> coordinateList;

    private Canvas canvas;
    private float selectedX = -1, selectedY = -1; //当前选中坐标
    private String titleText = "";
    private String selectedDate = "";
    private int yAxisCount = 6;

    public PayoffLineChart(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        axisTextPaint = new Paint();
        axisTextPaint.setColor(axisTextColor);
        axisTextPaint.setTextSize(axisTextSize);

        bgLinePaint = new Paint();
        bgLinePaint.setColor(normalLineColor);
        bgLinePaint.setStrokeWidth(normalLineWidth);

        titleTextPaint = new Paint();
        titleTextPaint.setColor(titleTextColor);
        titleTextPaint.setTextSize(titleTextSize);

        linePaint = new Paint();
        linePaint.setColor(lineColor);
        linePaint.setStrokeWidth(lineWidth);

        shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        shadowPaint.setColor(shadowColor);
        shadowPaint.setStyle(Paint.Style.FILL);

        selectedLinePaint = new Paint();
        selectedLinePaint.setColor(selectedLineColor);
        selectedLinePaint.setStrokeWidth(selectedLineWidth);

        shadowPath = new Path();
        yAxisYearStr.add("5.00%");
        yAxisYearStr.add("4.00%");
        yAxisYearStr.add("3.00%");
        yAxisYearStr.add("2.00%");
        yAxisYearStr.add("1.00%");
        yAxisYearStr.add("0.00%");
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);

        lineChartWidth = width - leftYOffset - rightOffset;
        cellHeight = height / 7;
        lineChartHeight = height - cellHeight * 2;
        cellWidth = lineChartWidth / 6;
        setMeasuredDimension((int) width, (int) height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        setLayerType(View.LAYER_TYPE_HARDWARE, null);
        this.canvas = canvas;
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        canvas.drawRect(0, 0, width, height, paint);
        drawTitleText(canvas);
        drawAxis(canvas);
        drawSelectedLine();
    }

    private void drawTitleText(Canvas canvas) {
        if (!TextUtils.isEmpty(titleText) && !TextUtils.isEmpty(selectedDate)) {
            titleTextPaint.setTextAlign(Paint.Align.LEFT);
            Rect rect1 = new Rect();
            titleTextPaint.getTextBounds(selectedDate, 0, selectedDate.length(), rect1);

            canvas.drawText(titleText, 20, cellHeight - 40, titleTextPaint);
            canvas.drawText(selectedDate, width - rect1.width() - 40, cellHeight - 40, titleTextPaint);
        } else {
            titleTextPaint.setTextAlign(Paint.Align.CENTER);
            if (MODE_TYPE == MODE_TYPE_YEAR_FLOAT) {
                canvas.drawText("*手指移至下方曲线图上，可查看近七日年化（%）", width / 2, cellHeight/ 2 + titleTextSize / 2, titleTextPaint);
            } else {
                canvas.drawText("*手指移至下方曲线图上，可查看万份收益（元）", width / 2, cellHeight/ 2 + titleTextSize / 2, titleTextPaint);
            }
        }
    }

    private void drawAxis(Canvas canvas) {
        if (MODE_TYPE == MODE_TYPE_YEAR_FLOAT) {
            yAxisStr.clear();
            yAxisStr.addAll(yAxisYearStr);
            yAxisMaxValue = 5;
        } else {
            yAxisMaxValue = getMax(axisValue);
            yAxisStr.clear();
            float yAxisCellValue = yAxisMaxValue / 4;
            for (int i = 4; i > -1; i--) {
                yAxisStr.add(df.format((double) yAxisCellValue * i));
            }
        }
        //绘制纵坐标
        axisTextPaint.setTextAlign(Paint.Align.LEFT);
        for (int i = 0; i < yAxisStr.size(); i++) {
            float y = cellHeight * (i + 1);
            if (i == yAxisStr.size() - 1) {
                canvas.drawText(yAxisStr.get(i), 20, y + axisTextSize / 2 - 20, axisTextPaint);
            } else {
                canvas.drawText(yAxisStr.get(i), 20, y + axisTextSize / 2, axisTextPaint);
            }
            canvas.drawLine(leftYOffset, y, width - rightOffset, y, bgLinePaint);
        }
        //绘制横坐标
        axisTextPaint.setTextAlign(Paint.Align.CENTER);
        if (MODE_DATE == MODE_WEEK) {
            canvas.drawText(xAxisStr[0].substring(5, 10),leftYOffset + 30, height - 40, axisTextPaint);
            canvas.drawText(xAxisStr[3].substring(5, 10),leftYOffset + cellWidth * 3, height - 40, axisTextPaint);
            canvas.drawText(xAxisStr[6].substring(5, 10), leftYOffset + lineChartWidth - 40, height - 40, axisTextPaint);
        } else if (MODE_DATE == MODE_MONTH) {
            canvas.drawText(xAxisStr[0].substring(5, 10),leftYOffset + 30, height - 40, axisTextPaint);
            canvas.drawText(xAxisStr[15].substring(5, 10),leftYOffset + cellWidth * 15, height - 40, axisTextPaint);
            canvas.drawText(xAxisStr[29].substring(5, 10), leftYOffset + lineChartWidth - 40, height - 40, axisTextPaint);
        } else {
            canvas.drawText(xAxisStr[0].substring(5, 10),leftYOffset + 30, height - 40, axisTextPaint);
            canvas.drawText(xAxisStr[45].substring(5, 10),leftYOffset + cellWidth * 45, height - 40, axisTextPaint);
            canvas.drawText(xAxisStr[89].substring(5, 10), leftYOffset + lineChartWidth - 40, height - 40, axisTextPaint);
        }

        //绘制折线和阴影
        if (axisValue != null && axisValue.size() > 0) {
            coordinateList = new ArrayList<>();
            drawLine(canvas);
        }

        
    }

    /**
     * 绘制折线和阴影
     */
    private void drawLine(Canvas canvas) {
//        values = new float[]{4.123f, 4.521f, 3.871f, 4.234f, 1.245f, 2.5432f, 4.234f};

        shadowPath.reset();
        for (int i = 0; i < axisValue.size(); i++) {
            float x = cellWidth * i + leftYOffset;
            float y = (1 - axisValue.get(i) / yAxisMaxValue) * lineChartHeight + cellHeight;
            coordinateList.add(new Coordinate(x, y));

            if (i < axisValue.size() - 1) {
                float x2 = cellWidth * (i + 1) + leftYOffset;
                float y2 = (1 - axisValue.get(i + 1) / yAxisMaxValue) * lineChartHeight + cellHeight;
                canvas.drawLine(x, y, x2, y2, linePaint);
                if (i == 0) {
                    shadowPath.moveTo(leftYOffset, cellHeight * yAxisCount);
                    shadowPath.lineTo(leftYOffset, y);
                    shadowPath.lineTo(x2, y2);
                } else {
                    shadowPath.lineTo(x2, y2);
                }
            }
            if (i == axisValue.size() - 1) {
                shadowPath.lineTo(x, cellHeight * yAxisCount);
                shadowPath.close();
            }
        }
//        shadowPath.setFillType(Path.FillType.EVEN_ODD);
        canvas.drawPath(shadowPath, shadowPaint);
    }

    private void drawSelectedLine() {
        if (selectedX != -1) {
            canvas.drawLine(selectedX, cellHeight, selectedX, cellHeight * yAxisCount, selectedLinePaint);
            canvas.drawLine(leftYOffset, selectedY, width - rightOffset, selectedY, selectedLinePaint);
        }
    }

    private float mLastMotionX = -1, mLastMotionY = -1;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean resume = false;
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case ACTION_MOVE:
                int deltaY = (int)(y - mLastMotionY);
                int deltaX = (int)(x - mLastMotionX);

                if (axisValue != null && axisValue.size() > 0 && coordinateList != null && coordinateList.size() > 0) {
                    for (int i = 0; i < coordinateList.size(); i++) {
                        Coordinate currCoordinate = coordinateList.get(i);
                        if (x > currCoordinate.x - cellWidth / 2 && x < currCoordinate.x + cellWidth / 2) {
                            selectedX = currCoordinate.x;
                            selectedY = currCoordinate.y;
                            if (MODE_TYPE == MODE_TYPE_YEAR_FLOAT) {
                                titleText = "近七日年化" + df2.format(axisValue.get(i)) + "%";
                            } else {
                                titleText = "万份收益" + df2.format(axisValue.get(i)) + "元";
                            }
                            selectedDate = xAxisStr[i];
                            invalidate();
                            return true;
                        }
                    }
                }

                if (Math.abs(deltaY) - Math.abs(deltaX) < 150) {
                    resume = true;
                } else {
                    resume = false;
                }

                break;
            case ACTION_DOWN:
                //按下或拖动，绘制坐标点对应的x y线
                if (axisValue != null && axisValue.size() > 0 && coordinateList != null && coordinateList.size() > 0) {
                    for (int i = 0; i < coordinateList.size(); i++) {
                        Coordinate currCoordinate = coordinateList.get(i);
                        if (x > currCoordinate.x - cellWidth / 2 && x < currCoordinate.x + cellWidth / 2) {
                            selectedX = currCoordinate.x;
                            selectedY = currCoordinate.y;
                            //绘制选中线和选中文字
                            if (MODE_TYPE == MODE_TYPE_YEAR_FLOAT) {
                                titleText = "近七日年化" + df2.format(axisValue.get(i)) + "%";
                            } else {
                                titleText = "万份收益" + df2.format(axisValue.get(i)) + "元";
                            }
                            selectedDate = xAxisStr[i];
                            invalidate();
                            return true;
                        }
                    }
                }
                break;
            case ACTION_UP:
                //拿起后，移除坐标线
                selectedX = -1;
                selectedY = -1;
                titleText = "";
                selectedDate = "";
                invalidateCustom();
                break;
        }

        return resume;
    }

    /**
     * 设置当前模式
     * @param typeMode 模式类型(近七日年化or万份收益) one of {@link #MODE_TYPE_YEAR_FLOAT} or {@link #MODE_TYPE_EARN}
     * @param dateMode 日期类型(近七日or一个月or三个月) one of {@link #MODE_WEEK} or {@link #MODE_MONTH} or {@link #MODE_3_MONTH}
     */
    public void setMode(int typeMode, int dateMode) {
        if (MODE_TYPE == typeMode && MODE_DATE == dateMode) {
            return;
        }
        MODE_TYPE = typeMode;
        MODE_DATE = dateMode;

        if (MODE_TYPE == MODE_TYPE_YEAR_FLOAT) {
            cellHeight = height / 7;
            lineChartHeight = height - cellHeight * 2;
            yAxisCount = 6;
        } else {
            cellHeight = height / 6;
            lineChartHeight = height - cellHeight * 2;
            yAxisCount = 5;
        }
        if (MODE_DATE == MODE_WEEK) {
            cellWidth = lineChartWidth / 6;
        } else if (MODE_DATE == MODE_MONTH) {
            cellWidth = lineChartWidth / 29;
        } else {
            cellWidth = lineChartWidth / 89;
        }
        invalidateCustom();
    }

    /**
     * 设置数据源
     * @param values y值数组
     * @param dates x值数组
     */
    public void setData(List values, String[] dates) {
        if (values == null || dates == null) {
            return;
        }
        this.axisValue.clear();
        this.axisValue.addAll(values);
        this.xAxisStr = dates;
        invalidateCustom();
    }

    private void invalidateCustom() {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            invalidate();
        } else {
            postInvalidate();
        }
    }

    private float getMax(List<Float> data) {
        if (data != null && data.size() > 0) {
            float max = data.get(0);
            for (int i = 1; i < data.size(); i++) {
                if (data.get(i) > max) {
                    max = data.get(i);
                }
            }
            int maxValue = (int) max;
            return maxValue + 1;
        } else {
            return 4;
        }
    }


    public interface OnValueSelectedListener {
        void onValueSelected();
    }

    class Coordinate implements Serializable {
        public float x;
        public float y;

        public Coordinate(float x, float y) {
            this.x = x;
            this.y = y;
        }
    }
}



